import { Component, OnInit, ChangeDetectorRef, Input, forwardRef, AfterViewInit } from '@angular/core'
import { ControlValueAccessor, FormGroup, FormBuilder, NG_VALUE_ACCESSOR, Validators, FormControl } from '@angular/forms'
import { of } from 'rxjs'
import { map, delay, take } from 'rxjs/operators'
import { toBoolean } from 'ng-zorro-antd'

import { IBiz } from '@shared/interfaces/biz'
import { IAamsItem, IAamsRequired } from '../aams-select/aams-select.interface'
import { I18NService } from '@core'
import { SettingsService } from '@delon/theme'
import {
  getAAMSAcquirer,
  getAAMSGroup,
  getAAMSMerchant,
  acquirerEditPermission,
  agentEditPermission,
  merchantEditPermission,
  getAAMSStore,
  storeEditPermission,
} from 'app/utils/helpers'
import { User } from '@shared/interfaces/user'

@Component({
  selector: 'app-aams-form',
  templateUrl: './aams-form.component.html',
  styles: [],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => AamsFormComponent),
      multi: true,
    },
  ],
})
export class AamsFormComponent implements ControlValueAccessor, OnInit, AfterViewInit {
  constructor(
    private fb: FormBuilder,
    private i18n: I18NService,
    private cdr: ChangeDetectorRef,
    private settings: SettingsService,
  ) {}

  private _value: IBiz = {}
  private _disabled = false

  @Input() IsRequired: IAamsRequired = {
    acquirer: false,
    group: false,
    merchant: false
  }

  chosenAcquirer: IAamsItem = {}
  chosenGroup: IAamsItem = {}
  chosenMerchant: IAamsItem = {}
  chosenStore: IAamsItem = {}
  form: FormGroup = this.fb.group({})
  onChange: (value: IBiz) => void = () => null
  onTouched: () => void = () => null

  @Input()
  set disabled(value: boolean) {
    this._disabled = toBoolean(value)
  }

  get disabled(): boolean {
    return this._disabled
  }

  set value(value: IBiz) {
    if (!value) {
      value = {}
    }

    this._value = value
    this.onChange(this._value)
  }

  get value(): IBiz {
    return this._value
  }

  ngOnInit() {
    const authUser = this.settings.user as User
    this.initAAMS(authUser)
    this.initForm()
  }

  initForm(): void {
    const authUser = this.settings.user as User
    const formOption = {
      // Setup acquirer select field
      acquirer: [
        {
          value: this.chosenAcquirer.code ? this.chosenAcquirer : null,
          disabled: acquirerEditPermission(authUser),
        },
        []
      ],
      acquirerName: [{ value: this.chosenAcquirer.name, disabled: true }],
      acquirerNameEN: [{ value: this.chosenAcquirer.nameEN, disabled: true }],
      group: [
        {
          value: this.chosenGroup.code ? this.chosenGroup : null,
          disabled: agentEditPermission(authUser),
        },
        []
      ],
      groupName: [{ value: this.chosenGroup.name, disabled: true }],
      groupNameEN: [{ value: this.chosenGroup.nameEN, disabled: true }],
      merchant: [
        {
          value: this.chosenMerchant.code ? this.chosenMerchant : null,
          disabled: merchantEditPermission(authUser),
        },
        []
      ],
      merchantName: [{ value: this.chosenMerchant.name, disabled: true }],
      merchantNameEN: [{ value: this.chosenMerchant.nameEN, disabled: true }],
      store: [
        {
          value: this.chosenStore.code ? this.chosenStore : null,
          disabled: storeEditPermission(authUser),
        },
        [Validators.required],
      ],
      storeName: [{ value: this.chosenStore.name, disabled: true }],
      storeNameEN: [{ value: this.chosenStore.nameEN, disabled: true }],
    }
    for (const [key, value] of Object.entries(this.IsRequired)) {
      if (value) {
        formOption[key][1] = [Validators.required]
      }
    }
    this.form = this.fb.group(formOption)
  }

  ngAfterViewInit(): void {
    setTimeout(() => {
      this.populateDefaultValue(this.value)
    }, 0)
  }

  initAAMS(authUser: User): void {
    this.chosenAcquirer = getAAMSAcquirer(authUser)
    this.chosenGroup = getAAMSGroup(authUser)
    this.chosenMerchant = getAAMSMerchant(authUser)
    this.chosenStore = getAAMSStore(authUser)
  }

  writeValue(val: IBiz): void {
    this.value = val
  }

  registerOnChange(fn: (value: IBiz) => void): void {
    this.onChange = fn
  }

  registerOnTouched(fn: () => void): void {
    this.onTouched = fn
  }

  setDisabledState?(isDisabled: boolean): void {
    this.disabled = isDisabled
    this.cdr.markForCheck()
  }

  /** 选中选项 */
  handleChosenAcquirer(value: IAamsItem): void {
    if (!value) {
      value = {}
    }

    this.chosenAcquirer = value
    this.form.get('acquirerName').setValue(value.name)
    this.form.get('acquirerNameEN').setValue(value.nameEN)
    this.value = Object.assign(this.value, {
      insCode: value.code,
      insName: value.name,
      insNameEN: value.nameEN,
    })
    this.resetGroup()
    this.resetMerchant()
    this.resetStore()
  }

  handleChosenGroup(value: IAamsItem | null): void {
    if (!value) {
      value = {}
    }

    this.chosenGroup = value
    this.form.get('groupName').setValue(value.name)
    this.form.get('groupNameEN').setValue(value.nameEN)
    this.value = Object.assign(this.value, {
      agentCode: value.code,
      agentName: value.name,
      agentNameEN: value.nameEN,
    })
    this.resetMerchant()
    this.resetStore()
  }

  handleChosenMerchant(value: IAamsItem | null): void {
    if (!value) {
      value = {}
    }

    this.chosenMerchant = value
    this.form.get('merchantName').setValue(value.name)
    this.form.get('merchantNameEN').setValue(value.nameEN)
    this.value = Object.assign(this.value, {
      intMerCode: value.code,
      merNum: value.num,
      merName: value.name,
      merNameEN: value.nameEN,
    })
    this.resetStore()
  }

  handleChosenStore(value: IAamsItem | null): void {
    if (!value) {
      value = {}
    }

    this.chosenStore = value
    this.form.get('storeName').setValue(value.name)
    this.form.get('storeNameEN').setValue(value.nameEN)
    this.value = Object.assign(this.value, {
      intStoreCode: value.code,
      storeNum: value.num,
      storeName: value.name,
      storeNameEN: value.nameEN,
    })
  }

  resetGroup(): void {
    const selectedGroup = this.form.get('group').value
    if (selectedGroup) {
      this.form.get('group').setValue(null)
      this.form.get('groupName').setValue('')
      this.form.get('groupNameEN').setValue('')
    }
  }

  resetMerchant(): void {
    const selectedMerchant = this.form.get('merchant').value
    if (selectedMerchant) {
      this.form.get('merchant').setValue(null)
      this.form.get('merchantName').setValue('')
      this.form.get('merchantNameEN').setValue('')
    }
  }

  resetStore(): void {
    const selectedStore = this.form.get('store').value
    if (selectedStore) {
      this.form.get('store').setValue(null)
      this.form.get('storeName').setValue('')
      this.form.get('storeNameEN').setValue('')
    }
  }

  trans(key: string, params?: Object): string {
    return this.i18n.fanyi(key, params)
  }

  private populateDefaultValue(value: IBiz) {
    of({ ...value })
      .pipe(
        map(val => {
          if (val.insCode) {
            this.populateAcquirer(val)
          }
          return val
        }),
        delay(500),
        map(val => {
          if (val.agentCode) {
            this.populateAgent(val)
          }
          return val
        }),
        delay(500),
        map(val => {
          if (val.intMerCode) {
            this.populateMerchant(val)
          }
          return val
        }),
        delay(500),
        map(val => {
          if (val.intStoreCode) {
            this.populateStore(val)
          }
          return val
        }),
        take(1),
      )
      .subscribe()
  }

  private populateAcquirer(val: IBiz) {
    this.chosenAcquirer = {
      num: val.insCode,
      code: val.insCode,
      name: val.insName,
      nameEN: val.insNameEN,
    }
    this.form.get('acquirer').setValue(this.chosenAcquirer)
    this.form.get('acquirerName').setValue(this.chosenAcquirer.name)
    this.form.get('acquirerNameEN').setValue(this.chosenAcquirer.nameEN)
  }

  private populateAgent(val: IBiz) {
    this.chosenGroup = {
      num: val.agentCode,
      code: val.agentCode,
      name: val.agentName,
      nameEN: val.agentNameEN,
    }
    this.form.get('group').setValue(this.chosenGroup)
    this.form.get('groupName').setValue(this.chosenGroup.name)
    this.form.get('groupNameEN').setValue(this.chosenGroup.nameEN)
  }

  private populateMerchant(val: IBiz) {
    this.chosenMerchant = {
      num: val.merNum,
      code: val.intMerCode,
      name: val.merName,
      nameEN: val.merNameEN,
    }
    this.form.get('merchant').setValue(this.chosenMerchant)
    this.form.get('merchantName').setValue(this.chosenMerchant.name)
    this.form.get('merchantNameEN').setValue(this.chosenMerchant.nameEN)
  }

  private populateStore(val: IBiz) {
    this.chosenStore = {
      num: val.storeNum,
      code: val.intStoreCode,
      name: val.storeName,
      nameEN: val.storeNameEN,
    }
    this.form.get('store').setValue(this.chosenStore)
    this.form.get('storeName').setValue(this.chosenStore.name)
    this.form.get('storeNameEN').setValue(this.chosenStore.nameEN)
  }
}
